package edu.caece.automaton;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Collection;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public abstract class AbstractAutomaton implements Automaton {
//throws StateNotInStatesException 
	protected Map<State, Collection<Transition>> transitions;
	protected Set<State> acceptStates;
	protected State startState;
	protected State currentState;
	protected State trashState = new StateImpl("_trash");
	protected final String SPLIT_STR = "~";
	protected static final Log LOGGER = LogFactory.getLog(AbstractAutomaton.class);
	
	public AbstractAutomaton(){
		transitions = new HashMap<State, Collection<Transition>>();
		acceptStates = new HashSet<State>();
		
	}
	
	public void addTransition(Transition newTransition) {
		if (this.transitions.containsKey(newTransition.getSourceState())){
			this.transitions.get(newTransition.getSourceState()).add(newTransition);
		}else{
			Collection<Transition> newTranCol = new ArrayList<Transition>();
			newTranCol.add(newTransition);
			this.transitions.put(newTransition.getSourceState(), newTranCol);
		}
	}

	public abstract boolean run(String word) ;
	
	public abstract boolean step(Character token);
	
	public abstract State peek(Character token);
	
	public abstract void reset();

	public void setStartState(State startState) {
		this.startState = startState;
		this.currentState = this.startState;
	}

	public State getCurrentState() {
		return this.currentState;
	}
	
	public void setAcceptStates(Set<State> states){
		this.acceptStates.addAll(states);
	}
	
	public void setTransitions(Set<Transition> transitions){
		for (Transition transition : transitions){
			addTransition(transition);
		}
	}
	
	public void setAcceptStatesFromNameSet(Set<String> statesNameSet){
		for(String name : statesNameSet){
			this.acceptStates.add(new StateImpl(name));
		}
	}
	
	public void setTransitionsFromStringSet(Set<String> transitionsStringSet){
		for(String transString : transitionsStringSet){
			String[] transArray = transString.split(SPLIT_STR);
			Transition t = new TransitionImpl(new StateImpl(transArray[0]),new StateImpl(transArray[2]), transArray[1]);
			addTransition(t);
		}
	}

	public State getStartState() {
		return this.startState;
	}

}
